package com.example.mattrigle;

import java.io.File;
import java.io.IOException;

import com.example.mattrigle.CustomAnimation.TimerListener;
import com.example.mattrigle.SeekBar.SeekBarListener;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class GameCanvas extends View implements SeekBarListener,
		SpinClickListener {

	// ==========================================================
	// Delegate & Callback
	// ==========================================================
	public abstract interface InteractListener {
		public void onBeginDrag(SeekBar obj, float value, long currentTime,
				Point position);

		public void onValueChange(SeekBar obj, float value, long currentTime,
				Point position);

		public void onEndDrag(SeekBar obj, float value, long currentTime,
				long elapsedTime, Point position);
	}

	public abstract interface InteractClickListener {
		public void onClick(SpinButton obj, float value, long currentTime,
				Point location);
	}

	// ==========================================================
	// Constants
	// ==========================================================
	private int TRACK_HEIGHT = 50;

	private class GameCanvasOption {
		public boolean isViewForAnimate = false;
		public int align = ALIGN_CENTER;
		public int valign = VALIGN_MIDDLE;
		public int pos_hand = POS_HAND_SLIDE;
		public Point position = new Point(0, 0);
		public boolean isShowAngle = true;
		public boolean isShowSeekBar = true;
		public boolean isLock = false;
		public float thumb_length = 1f;
		public float scale = 0.4f;
		public int num_float_bit = 1;
		public boolean isEnableCacheValue = true;
		public int mode = MODE_DISPLAY;
		public boolean isHideCorner = true;
		public boolean multiCorner = false;
		public boolean isHideHand = true;
		public boolean isMultiActive = false;
		public boolean isCosActive = true;
		public boolean isHideArc = false;
		public boolean isHideLabel = false;

		public GameCanvasOption clone() {
			GameCanvasOption tmp = new GameCanvasOption();
			tmp.isViewForAnimate = isViewForAnimate;
			tmp.align = align;
			tmp.isViewForAnimate = isViewForAnimate;
			tmp.align = align;
			tmp.valign = valign;
			tmp.position = position;
			tmp.multiCorner = multiCorner;
			tmp.isShowAngle = isShowAngle;
			tmp.isShowSeekBar = isShowSeekBar;
			tmp.isLock = isLock;
			tmp.thumb_length = thumb_length;
			tmp.isHideArc = isHideArc;
			tmp.scale = scale;
			tmp.num_float_bit = num_float_bit;
			tmp.isEnableCacheValue = isEnableCacheValue;
			tmp.mode = mode;
			tmp.isHideCorner = isHideCorner;
			tmp.isHideHand = isHideHand;
			tmp.isMultiActive = isMultiActive;
			tmp.isCosActive = isCosActive;
			tmp.isHideLabel = isHideLabel;
			return tmp;
		}
	}

	// ==========================================================
	// Field
	// ==========================================================
	private Paint tanPaint = new Paint();
	private Paint anglePaint = new Paint();
	private Paint markAnglePaint = new Paint();
	private CornerDrawable corner_cos_anim;
	private CornerDrawable corner_sin_anim;

	private RectF cosRectF = null;
	private RectF sinRectF = null;
	private Point offset = new Point(0, 0);

	private int doc_width = 120, doc_height = 260;
	private int object_width = 120, object_height = 260;
	private float cosDegree = 0f;

	private SeekBar cosSeekBar, sinSeekBar, tanSeekBar;
	private SeekBar mCosSeekBar, mSinSeekBar;

	private GameCanvasOption option = new GameCanvasOption();

	// ==========================================================
	// Properties
	// ==========================================================
	public static final int ALIGN_CENTER = 0;
	public static final int ALIGN_LEFT = 1;
	public static final int ALIGN_RIGHT = 2;

	public int getAlign() {
		return this.option.align;
	}

	public void setAlign(int align) {
		switch (align) {
		case ALIGN_CENTER:
		case ALIGN_LEFT:
		case ALIGN_RIGHT:
			this.option.align = align;
			break;
		default:
			this.option.align = ALIGN_CENTER;
			break;
		}
		calPos();
	}

	public static final int VALIGN_MIDDLE = 0;
	public static final int VALIGN_TOP = 1;
	public static final int VALIGN_BOTTOM = 2;

	public int getValign() {
		return this.option.valign;
	}

	public void setValign(int valign) {
		switch (valign) {
		case ALIGN_CENTER:
		case ALIGN_LEFT:
		case ALIGN_RIGHT:
			this.option.valign = valign;
			break;
		default:
			this.option.valign = VALIGN_MIDDLE;
			break;
		}
		calPos();
	}

	public void setPosition(int x, int y) {
		this.option.position.x = x;
		this.option.position.y = y;
		calPos();
	}

	public Point getPosition() {
		return this.option.position;
	}

	public boolean IsShowAngle() {
		return this.option.isShowAngle;
	}

	public void setShowAngle(boolean isShowAngle) {
		this.option.isShowAngle = isShowAngle;
		this.invalidate();
	}

	public boolean IsShowSeekBar() {
		return this.option.isShowSeekBar;
	}

	public void setShowSeekBar(boolean isShowSeekBar) {
		this.option.isShowSeekBar = isShowSeekBar;
		this.invalidate();
	}

	public boolean getLockSeekBar() {
		return this.option.isLock;
	}

	public void LockSeekBar(boolean isLock) {
		this.option.isLock = isLock;
	}

	public float getMaxTanThumbnailLength() {
		return this.option.thumb_length;
	}

	public void setMaxTanThumbnailLength(float length) {
		this.option.thumb_length = length > 1f ? 1f : length < 0.5f ? 0.5f
				: length;
		mCosSeekBar.setMaximumLength(this.option.thumb_length);
		mSinSeekBar.setMaximumLength(this.option.thumb_length);
	}

	public float getScale() {
		return this.option.scale;
	}

	public void setScale(float scale) {
		this.option.scale = scale < 0.1f ? 0.1f : scale > 0.6f ? 0.6f : scale;
		this.sinSeekBar.setScale(scale);
		this.cosSeekBar.setScale(scale);
		this.tanSeekBar.setScale(scale);
		calSize();
	}

	public int getNumOfFloatBit() {
		return this.option.num_float_bit;
	}

	public void setNumOfFloatBit(int num_float_bit) {
		this.option.num_float_bit = num_float_bit < 1 ? 1
				: num_float_bit > 6 ? 6 : num_float_bit;
		this.invalidate();
	}

	public boolean isEnableCacheValue() {
		return this.option.isEnableCacheValue;
	}

	public void setEnableCacheValue(boolean isEnableCacheValue) {
		this.option.isEnableCacheValue = isEnableCacheValue;
	}

	public boolean getMultiCorner() {
		return this.option.multiCorner;
	}

	public void setMultiCorner(boolean multiCorner) {
		this.option.multiCorner = multiCorner;
		this.invalidate();
	}

	public boolean IsHideCorner() {
		return this.option.isHideCorner;
	}

	public void setHideCorner(boolean isHideCorner) {
		this.option.isHideCorner = isHideCorner;

		if (corner_sin_anim == null) {
			try {
				corner_sin_anim = new CornerDrawable(this,
						(new File(
								CornerDrawable.getLocalPath(this.getContext()))
								.exists()) ? null : getResources()
								.openRawResource(R.raw.cartoon1), true);

			} catch (NotFoundException e) {
				corner_sin_anim = null;
			} catch (IOException e) {
				corner_sin_anim = null;
			}
			if (corner_sin_anim != null) {
				corner_sin_anim.setSmoothScale(0.0025f * this.getWidth());
				corner_sin_anim.setForeground(new Rect(
						mSinSeekBar.getCursorX() - 40,
						mSinSeekBar.getCursorY() - 60,
						mSinSeekBar.getCursorX() + 60,
						mSinSeekBar.getCursorY() + 40));
			}

		}
		if (corner_cos_anim == null) {
			try {
				corner_cos_anim = new CornerDrawable(this,
						(new File(
								CornerDrawable.getLocalPath(this.getContext()))
								.exists()) ? null : getResources()
								.openRawResource(R.raw.cartoon1), true);

			} catch (NotFoundException e) {
				corner_cos_anim = null;
			} catch (IOException e) {
				corner_cos_anim = null;
			}

			if (corner_cos_anim != null) {
				corner_cos_anim.setSmoothScale(0.0025f * this.getWidth());
				corner_cos_anim.setForeground(new Rect(
						mCosSeekBar.getCursorX() - 40,
						mCosSeekBar.getCursorY() - 60,
						mCosSeekBar.getCursorX() + 60,
						mCosSeekBar.getCursorY() + 40));

			}

		}
		if (!this.option.isHideCorner) {
			corner_cos_anim.start();
			corner_sin_anim.start();
		} else {
			corner_cos_anim.stop();
			corner_sin_anim.stop();
			this.invalidate();
		}
	}

	public static final int POS_HAND_SEEKBAR = 0;
	public static final int POS_HAND_SLIDE = 1;
	public static final int POS_HAND_BOTH = 2;

	public int getPosHand() {
		return this.option.pos_hand;
	}

	public void setPosHand(int pos_hand) {
		this.option.pos_hand = (pos_hand == POS_HAND_SEEKBAR
				|| pos_hand == POS_HAND_SLIDE || pos_hand == POS_HAND_BOTH) ? pos_hand
				: POS_HAND_SLIDE;
		this.invalidate();
	}

	public boolean IsHideLabel() {
		return this.option.isHideLabel;
	}

	public void setHideLabel(boolean isHideLabel) {
		this.option.isHideLabel = isHideLabel;

		this.sinSeekBar.setHideLabel(isHideLabel);
		this.mSinSeekBar.setHideLabel(isHideLabel);
		this.cosSeekBar.setHideLabel(isHideLabel);
		this.mCosSeekBar.setHideLabel(isHideLabel);
		this.invalidate();
	}

	public boolean IsHideHand() {
		return this.option.isHideHand;
	}

	public void setHideHand(boolean isHideHand) {
		this.option.isHideHand = isHideHand;

		this.sinSeekBar.setHideHand(isHideHand || this.option.isViewForAnimate
				|| (this.option.isCosActive && !this.option.isMultiActive));
		this.mSinSeekBar.setHideHand(isHideHand
				|| (this.option.isCosActive && !this.option.isMultiActive));
		this.cosSeekBar.setHideHand(isHideHand || this.option.isViewForAnimate
				|| (!this.option.isCosActive && !this.option.isMultiActive));
		this.mCosSeekBar.setHideHand(isHideHand
				|| (!this.option.isCosActive && !this.option.isMultiActive));
		this.invalidate();
	}

	public void setCosActive(boolean isCosActive) {
		this.option.isCosActive = isCosActive;

		this.sinSeekBar.setEnable(!isCosActive);
		this.sinSeekBar.setHideLabel(isCosActive);
		this.mSinSeekBar.setEnable(!isCosActive);

		this.cosSeekBar.setEnable(isCosActive);
		this.cosSeekBar.setHideLabel(!isCosActive);
		this.mCosSeekBar.setEnable(isCosActive);

		setHideHand(this.option.isHideHand);
	}

	private float line_width = 1f;

	public float getLineWidth() {
		return line_width * 2;
	}

	public void setLineWidth(int line_width) {
		this.line_width = (line_width < 1) ? 1 : line_width;
		this.tanPaint.setStrokeWidth(line_width);

		this.cosSeekBar.setLineWidth(line_width / 3);
		this.sinSeekBar.setLineWidth(line_width / 3);
		this.tanSeekBar.setLineWidth(line_width / 3);
		this.mCosSeekBar.setLineWidth(line_width);
		this.mSinSeekBar.setLineWidth(line_width);
	}

	public boolean IsMultiActive() {
		return this.option.isMultiActive;
	}

	public void setMultiActive(boolean isMultiActive) {
		this.option.isMultiActive = isMultiActive;
		this.sinSeekBar.setEnable(isMultiActive);
		this.mSinSeekBar.setEnable(isMultiActive);
		this.cosSeekBar.setEnable(isMultiActive);
		this.sinSeekBar.setHideLabel(!isMultiActive);
		this.cosSeekBar.setHideLabel(!isMultiActive);
		this.mCosSeekBar.setEnable(isMultiActive);
		if (!isMultiActive) {
			this.setCosActive(this.option.isCosActive);

			if (!this.option.isCosActive)
				this.sinSeekBar.setHideLabel(true);
			else
				this.cosSeekBar.setHideLabel(true);
		}
		setHideHand(this.option.isHideHand);
		setHideCorner(this.option.isHideCorner);
		this.invalidate();
	}

	private int solveAngle = 45;

	public void setIcon(int solveAngle) {
		this.solveAngle = solveAngle;
		this.invalidate();
	}

	// =====================================================================

	private float weight_point = 0.0025f;

	public void setWeightPoint(float weight_point) {
		this.weight_point = weight_point;
	}

	private Drawable iconSpin30, labelDrawable, inactiveLabelDrawable;
	private Drawable plusDrawable, plusInactiveDrawable, plusHoverDrawable;
	private Drawable minusDrawable, minusInactiveDrawable, minusHoverDrawable;
	private Paint spinPaint = new Paint();
	private Paint spinInactivePaint = new Paint();
	private Paint spinCPaint = new Paint();
	private Paint spinInactiveCPaint = new Paint();
	private Paint titlePaint = new Paint();
	private Paint titleInactivePaint = new Paint();
	private Point vtSinSpinTxt = new Point(), vtCosSpinTxt = new Point();
	private Paint lineBarPaint = new Paint();
	private Paint lineBarFillPaint = new Paint();

	private Rect iconSin, iconCos;
	private SpinButton cosLabelBodaries, sinLabelBodaries;
	private SpinButton cosPlusBodaries, sinPlusBodaries;
	private SpinButton cosMinusBodaries, sinMinusBodaries;
	Drawable drawableBG_Red = getResources().getDrawable(R.drawable.r_spin_canvas);
	Drawable drawableBG_Blue = getResources().getDrawable(R.drawable.b_spin_canvas);
	

	private Rect rectSinBg, rectCosBg;

	// =====================================================================

	// ==========================================================
	// Constructor
	// ==========================================================
	// For xml layout
	public GameCanvas(Context context, AttributeSet attrs) {
		super(context, attrs);
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.GameCanvas);
		this.option.isViewForAnimate = a.getBoolean(
				R.styleable.GameCanvas_is_animation_view, false);

		a.recycle();

		loadContent(context);
		Initialize();
	}

	// For activity ->setContentView
	public GameCanvas(Context context, boolean isViewForAnimate) {
		super(context);

		this.option.isViewForAnimate = isViewForAnimate;
		loadContent(context);
		Initialize();
	}

	// ==========================================================
	// Process & Operand Method
	// ==========================================================
	float aw = 1f;

	private void calPos() {
		aw = ((float) object_width) / 320f;
		if (!this.option.isViewForAnimate)
			object_height = (int) ((doc_height > object_width
					+ (TRACK_HEIGHT * 4 * aw * 1.1)) ? object_width
					+ (TRACK_HEIGHT * 4 * aw * 1.1) : doc_height);
		else
			object_height = object_width;

		switch (this.option.align) {
		case ALIGN_CENTER:
			offset.x = this.option.position.x
					+ ((doc_width - object_width) / 2);
			if (this.option.mode != MODE_DISPLAY)
				offset.x = offset.x / 2;
			break;
		case ALIGN_LEFT:
			offset.x = this.option.position.x
					+ (int) (((this.sinSeekBar.getThumbWidth() > sinSeekBar
							.getLabelWidth() ? 1.1f * aw
							* (sinSeekBar.getThumbWidth() + 40) : 1.1f * aw
							* (sinSeekBar.getLabelWidth() + 40)) / 2));
			break;
		case ALIGN_RIGHT:
			offset.x = this.option.position.x
					+ (doc_width - object_width - this.sinSeekBar
							.getThumbWidth() / 2);
			break;
		}
		switch (this.option.valign) {
		case VALIGN_MIDDLE:
			offset.y = this.option.position.y
					+ this.sinSeekBar.getThumbHeight() / 2
					+ ((doc_height - object_height) / 2);
			break;
		case VALIGN_TOP:
			offset.y = this.option.position.y
					+ this.sinSeekBar.getThumbHeight() / 2;
			break;
		case VALIGN_BOTTOM:
			offset.y = this.option.position.y
					+ (doc_height - object_height - this.sinSeekBar
							.getThumbHeight() / 2);
			break;
		}

		int TRACKER_HEIGHT = (int) (50f * aw);
		tanSeekBar.setPosition(offset.x, offset.y + object_width
				+ (int) ((float) (1f / 2f) * TRACKER_HEIGHT));

		int shap_size = (int) (TRACKER_HEIGHT * 0.8);
		int cy = offset.y + object_width
				+ (int) ((float) (3f / 2f) * TRACKER_HEIGHT);
		int space = (int) (aw * 30);
		cosSeekBar.setPosition(offset.x, cy);

		cy += 5;

		vtCosSpinTxt.x = offset.x + cosSeekBar.getWidth() + (int) (space * 0.5)+ (int) (13 * aw);
		vtCosSpinTxt.y = cy + (int) (24 * aw);

		iconCos = new Rect(offset.x + cosSeekBar.getWidth()+ (int) (13 * aw)
				+ (int) (space * 2.3), cy, offset.x + cosSeekBar.getWidth()
				+ (int) (shap_size * 0.8) + (int) (space * 2.3)+ (int) (13 * aw), cy
				+ (int) (shap_size * 0.8));

		cosMinusBodaries.bondary = new Rect(iconCos.right, cy, iconCos.right
				+ shap_size, cy + shap_size);

		cosLabelBodaries.bondary = new Rect(cosMinusBodaries.bondary.right, cy,
				cosMinusBodaries.bondary.right + (int) (space * 0.8)
						+ (int) (shap_size * 1.3), cy + shap_size);

		cosPlusBodaries.bondary = new Rect(cosLabelBodaries.bondary.right, cy,
				cosLabelBodaries.bondary.right + shap_size, cy + shap_size);

		int sy = offset.y + object_width
				+ (int) ((float) (5f / 2f) * TRACKER_HEIGHT);
		sinSeekBar.setPosition(offset.x, sy);

		sy += 10;

		vtSinSpinTxt.x = offset.x + sinSeekBar.getWidth() + (int) (space * 0.5)+ (int) (13 * aw);
		vtSinSpinTxt.y = sy + (int) (24 * aw);
		iconSin = new Rect(offset.x + sinSeekBar.getWidth()+ (int) (13 * aw)
				+ (int) (space * 2.3), sy, offset.x + sinSeekBar.getWidth()
				+ (int) (shap_size * 0.8) + (int) (space * 2.3)+ (int) (13 * aw), sy
				+ (int) (shap_size * 0.8));
		sinMinusBodaries.bondary = new Rect(iconSin.right, sy, iconSin.right
				+ shap_size, sy + shap_size);

		sinLabelBodaries.bondary = new Rect(sinMinusBodaries.bondary.right, sy,
				sinMinusBodaries.bondary.right + (int) (space * 0.8)
						+ (int) (shap_size * 1.3), sy + shap_size);
		sinPlusBodaries.bondary = new Rect(sinLabelBodaries.bondary.right, sy,
				sinLabelBodaries.bondary.right + shap_size, sy + shap_size);

		mSinSeekBar.setPosition(offset.x, offset.y);
		mCosSeekBar.setPosition(offset.x, offset.y + object_width
				- (int) ((float) (1f / 2f) * TRACK_HEIGHT));

		int mWidth = (int)(mCosSeekBar.getProgress()*mCosSeekBar.getWidth());
		mWidth = (int)(mWidth>0.15f*object_width?0.15f*object_width:mWidth);
		int mHeight = (int)((mSinSeekBar.getProgress())*mSinSeekBar.getHeight());
		mHeight = (int)(mHeight>0.15f*object_width?0.15f*object_width:mHeight);
		
		cosRectF = new RectF(mCosSeekBar.getCursorX() - mWidth,
				mCosSeekBar.getCursorY() - mWidth, mCosSeekBar.getCursorX()
						+ mWidth, mCosSeekBar.getCursorY() + mWidth);
		sinRectF = new RectF(mSinSeekBar.getCursorX() - mHeight,
				mSinSeekBar.getCursorY() - mHeight, mSinSeekBar.getCursorX()
						+ mHeight, mSinSeekBar.getCursorY() + mHeight);

		rectSinBg = new Rect(vtSinSpinTxt.x-5,sinPlusBodaries.bondary.top-5,sinPlusBodaries.bondary.right+5,sinPlusBodaries.bondary.bottom+5);
		rectCosBg = new Rect(vtCosSpinTxt.x-5,cosPlusBodaries.bondary.top-5,cosPlusBodaries.bondary.right+5,cosPlusBodaries.bondary.bottom+5);
		
		if (corner_sin_anim != null)
			corner_sin_anim.setForeground(new Rect(
					mSinSeekBar.getCursorX() - 40,
					mSinSeekBar.getCursorY() - 60,
					mSinSeekBar.getCursorX() + 60,
					mSinSeekBar.getCursorY() + 40));
		if (corner_cos_anim != null)
			corner_cos_anim.setForeground(new Rect(
					mCosSeekBar.getCursorX() - 40,
					mCosSeekBar.getCursorY() - 60,
					mCosSeekBar.getCursorX() + 60,
					mCosSeekBar.getCursorY() + 40));
		this.invalidate();
		isResize = true;

	}

	private Boolean isResize = false;

	public Point getOriginPosition() {
		return isResize ? mCosSeekBar.getPosition() : new Point();
	}

	private void calSize() {
		object_width = (int) (doc_height * this.option.scale);
		if (object_width > doc_width * 0.75f)
			object_width = (int) (doc_width * 0.75f);

		float aw = ((float) object_width) / 320f;

		cosSeekBar.setHeight((int) (aw * TRACK_HEIGHT));
		cosSeekBar.setWidth(object_width);

		sinSeekBar.setHeight((int) (aw * TRACK_HEIGHT));
		sinSeekBar.setWidth(object_width);

		tanSeekBar.setHeight((int) (aw * TRACK_HEIGHT));
		tanSeekBar.setWidth(object_width);

		mCosSeekBar.setHeight(TRACK_HEIGHT);
		mCosSeekBar.setWidth(object_width);

		mSinSeekBar.setHeight(object_width);
		mSinSeekBar.setWidth(TRACK_HEIGHT);

		this.tanPaint.setStrokeWidth(aw * line_width);
		this.cosSeekBar.setLineWidth((int) (aw * line_width / 2));
		this.sinSeekBar.setLineWidth((int) (aw * line_width / 2));
		this.tanSeekBar.setLineWidth((int) (aw * line_width / 2));
		this.mCosSeekBar.setLineWidth((int) (aw * line_width));
		this.mSinSeekBar.setLineWidth((int) (aw * line_width));
		lineBarPaint.setStrokeWidth(aw * line_width / 2);
		lineBarFillPaint.setStrokeWidth(aw * line_width / 2);

		this.cosSeekBar.setSmoothScale(aw);
		this.sinSeekBar.setSmoothScale(aw);
		this.tanSeekBar.setSmoothScale(aw);

		tanPaint.setTextSize(25 * aw);
		anglePaint.setTextSize(55 * aw);
		tanPaint.setStrokeWidth((int) (aw * line_width));
		spinPaint.setTextSize(62 * aw);
		spinInactivePaint.setTextSize(62 * aw);
		spinCPaint.setTextSize(50 * aw);
		spinInactiveCPaint.setTextSize(50 * aw);
		titlePaint.setTextSize(62 * aw);
		titleInactivePaint.setTextSize(62 * aw);

		calPos();
		newStageWithAngle(true, this.cosDegree);
	}

	private void calProgress(SeekBar obj, float progress, boolean saveData) {
		if (progress < 0)
			progress = 0;
		if (progress > 1)
			progress = 1;
		if (obj == cosSeekBar) {
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "cosSeekValue",
						progress + "f");
			mCosSeekBar.setProgress(cosSeekBar.getProgress()
					* this.option.thumb_length);
			double Vl_w = Math.sin(Math.acos(progress)) * obj.getWidth();
			cosDegree = (float) ((180 / Math.PI) * (Math.acos(progress)));
			sinSeekBar.setProgress((float) (Vl_w / obj.getWidth()));
			mSinSeekBar.setProgress(sinSeekBar.getProgress()
					* this.option.thumb_length);
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "sinSeekValue",
						sinSeekBar.getProgress() + "f");
		}
		if (obj == sinSeekBar) {
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "sinSeekValue",
						progress + "f");
			mSinSeekBar.setProgress(sinSeekBar.getProgress()
					* this.option.thumb_length);
			double Hl_h = Math.cos(Math.asin(progress)) * obj.getWidth();
			cosDegree = (float) ((180 / Math.PI) * (Math.asin(progress)));
			cosSeekBar.setProgress((float) (Hl_h / obj.getWidth()));
			mCosSeekBar.setProgress(cosSeekBar.getProgress()
					* this.option.thumb_length);
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "cosSeekValue",
						cosSeekBar.getProgress() + "f");
		}
		if (obj == mCosSeekBar) {
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "cosSeekValue",
						progress / this.option.thumb_length + "f");
			cosSeekBar.setProgress(mCosSeekBar.getProgress()
					/ this.option.thumb_length);

			double Vl_w = Math.sin(Math.acos(cosSeekBar.getProgress()))
					* obj.getWidth();
			cosDegree = (float) ((180 / Math.PI) * (Math.acos(cosSeekBar
					.getProgress())));
			sinSeekBar.setProgress((float) (Vl_w / obj.getWidth()));

			mSinSeekBar.setProgress(sinSeekBar.getProgress()
					* this.option.thumb_length);
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "sinSeekValue",
						sinSeekBar.getProgress() + "f");
		}


		int mWidth = (int)(mCosSeekBar.getProgress()*mCosSeekBar.getWidth());
		mWidth = (int)(mWidth>0.15f*object_width?0.15f*object_width:mWidth);
		int mHeight = (int)((mSinSeekBar.getProgress())*mSinSeekBar.getHeight());
		mHeight = (int)(mHeight>0.15f*object_width?0.15f*object_width:mHeight);
		
		sinRectF = new RectF(mSinSeekBar.getCursorX() - mHeight,
				mSinSeekBar.getCursorY() - mHeight, mSinSeekBar.getCursorX()
						+ mHeight, mSinSeekBar.getCursorY() + mHeight);

		if (obj == mSinSeekBar) {
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "sinSeekValue",
						mSinSeekBar.getProgress(true)
								/ this.option.thumb_length + "f");
			sinSeekBar.setProgress(mSinSeekBar.getProgress(true)
					/ this.option.thumb_length);
			mSinSeekBar.setProgress(sinSeekBar.getProgress()
					* this.option.thumb_length);

			double Hl_h = Math.cos(Math.asin(sinSeekBar.getProgress()))
					* obj.getWidth();
			cosDegree = (float) ((180 / Math.PI) * (Math.asin(sinSeekBar
					.getProgress())));
			cosSeekBar.setProgress((float) (Hl_h / obj.getWidth()));

			mCosSeekBar.setProgress(cosSeekBar.getProgress()
					* this.option.thumb_length);
			if (saveData && this.option.isEnableCacheValue)
				UDataStorage.setStrData(this.getContext(), "cosSeekValue",
						cosSeekBar.getProgress(true) + "f");

			mHeight = (int) (((obj == mSinSeekBar) ? mSinSeekBar.getProgress()
					: mSinSeekBar.getProgress()) * mSinSeekBar.getHeight());

			mHeight = (int)((mSinSeekBar.getProgress())*mSinSeekBar.getHeight());
			mHeight = (int)(mHeight>0.15f*object_width?0.15f*object_width:mHeight);
			
			sinRectF = new RectF(mSinSeekBar.getCursorX() - mHeight,
					mSinSeekBar.getCursorY() - mHeight,
					mSinSeekBar.getCursorX() + mHeight,
					mSinSeekBar.getCursorY() + mHeight);

		}

		tanSeekBar.setProgress(1f);

		cosRectF = new RectF(mCosSeekBar.getCursorX() - mWidth,
				mCosSeekBar.getCursorY() - mWidth, mCosSeekBar.getCursorX()
						+ mWidth, mCosSeekBar.getCursorY() + mWidth);

		if (corner_sin_anim != null)
			corner_sin_anim.setForeground(new Rect(
					mSinSeekBar.getCursorX() - 40,
					mSinSeekBar.getCursorY() - 60,
					mSinSeekBar.getCursorX() + 60,
					mSinSeekBar.getCursorY() + 40));
		if (corner_cos_anim != null)
			corner_cos_anim.setForeground(new Rect(
					mCosSeekBar.getCursorX() - 40,
					mCosSeekBar.getCursorY() - 60,
					mCosSeekBar.getCursorX() + 60,
					mCosSeekBar.getCursorY() + 40));

	}

	private void loadContent(Context context) {

		cosSeekBar = new SeekBar(context, this, SeekBar.HORIZONTAL, false);
		if (!this.option.isViewForAnimate)
			cosSeekBar.setOnValueChanged(this);
		sinSeekBar = new SeekBar(context, this, SeekBar.HORIZONTAL, false);
		if (!this.option.isViewForAnimate)
			sinSeekBar.setOnValueChanged(this);
		tanSeekBar = new SeekBar(context, this, SeekBar.HORIZONTAL, false);
		if (!this.option.isViewForAnimate)
			tanSeekBar.setOnValueChanged(this);

		mCosSeekBar = new SeekBar(context, this, SeekBar.HORIZONTAL, true);
		if (!this.option.isViewForAnimate)
			mCosSeekBar.setOnValueChanged(this);
		mSinSeekBar = new SeekBar(context, this, SeekBar.VERTICAL, true);
		if (!this.option.isViewForAnimate)
			mSinSeekBar.setOnValueChanged(this);

		tanPaint.setColor(0xff86c5f8);
		tanPaint.setStyle(Style.STROKE);
		tanPaint.setAntiAlias(true);

		Typeface face = Typeface.createFromAsset(getContext().getAssets(),
				"fonts/THA0085.ttf");
		anglePaint.setTypeface(face);
		anglePaint.setARGB(255, 58, 58, 58);
		anglePaint.setStyle(Style.FILL_AND_STROKE);
		anglePaint.setAntiAlias(true);
		anglePaint.setStrokeWidth(1);

		spinPaint.setTypeface(face);
		spinPaint.setAntiAlias(true);
		spinPaint.setARGB(255, 58, 58, 58);

		spinCPaint.setTypeface(face);
		spinCPaint.setAntiAlias(true);
		spinCPaint.setARGB(255, 58, 58, 58);

		spinInactivePaint.setTypeface(face);
		spinInactivePaint.setAntiAlias(true);
		spinInactivePaint.setARGB(255, 58, 58, 58);

		titlePaint.setTypeface(face);
		titlePaint.setAntiAlias(true);
		titlePaint.setARGB(255, 58, 58, 58);

		titleInactivePaint.setTypeface(face);
		titleInactivePaint.setAntiAlias(true);
		titleInactivePaint.setARGB(255, 120, 120, 120);

		markAnglePaint.setColor(Color.argb(255, 255, 200, 0));
		markAnglePaint.setStyle(Style.FILL_AND_STROKE);
		markAnglePaint.setAntiAlias(true);
		markAnglePaint.setStrokeJoin(Paint.Join.ROUND);
		markAnglePaint.setStrokeWidth(this.line_width);

		lineBarPaint.setColor(Color.rgb(255, 150, 0));
		lineBarPaint.setStyle(Style.FILL);
		lineBarPaint.setAntiAlias(true);
		lineBarPaint.setStrokeJoin(Paint.Join.ROUND);
		lineBarPaint.setStrokeWidth(this.line_width);

		lineBarFillPaint.setColor(Color.argb(100, 255, 200, 0));
		lineBarFillPaint.setStyle(Style.FILL_AND_STROKE);
		lineBarFillPaint.setAntiAlias(true);
		lineBarFillPaint.setStrokeJoin(Paint.Join.ROUND);
		lineBarFillPaint.setStrokeWidth(this.line_width);

		cosSeekBar.setTheme(SeekBar.THEME_GREEN_INVERT);
		sinSeekBar.setTheme(SeekBar.THEME_RED_INVERT);
		tanSeekBar.setTheme(SeekBar.THEME_BLUE);
		mCosSeekBar.setTheme(SeekBar.THEME_GREEN);
		mSinSeekBar.setTheme(SeekBar.THEME_RED);

		plusDrawable = context.getResources().getDrawable(
				R.drawable.btn_plus_hover);
		
		minusDrawable = context.getResources().getDrawable(
				R.drawable.btn_minus_hover);

		plusInactiveDrawable = context.getResources().getDrawable(
				R.drawable.btn_plus_inactive);
		
		minusInactiveDrawable = context.getResources().getDrawable(
				R.drawable.btn_minus_inactive);

		plusHoverDrawable = context.getResources().getDrawable(
				R.drawable.btn_plus_hover);
		
		minusHoverDrawable = context.getResources().getDrawable(
				R.drawable.btn_minus_hover);

		iconSpin30 = context.getResources().getDrawable(R.drawable.zeta30);
		labelDrawable = context.getResources().getDrawable(
				R.drawable.label_region);
		
		inactiveLabelDrawable = context.getResources().getDrawable(
				R.drawable.inactive_label_region);
		
		cosLabelBodaries = new SpinButton();
		cosLabelBodaries.listener = this;
		sinLabelBodaries = new SpinButton();
		sinLabelBodaries.listener = this;

		cosPlusBodaries = new SpinButton();
		cosPlusBodaries.listener = this;
		sinPlusBodaries = new SpinButton();
		sinPlusBodaries.listener = this;

		cosMinusBodaries = new SpinButton();
		cosMinusBodaries.listener = this;
		sinMinusBodaries = new SpinButton();
		sinMinusBodaries.listener = this;

	}

	// ==========================================================
	// Public Method
	// ==========================================================
	private static final int MODE_DISPLAY = 5;
	public static final int MODE_CAPTURE_FULL = 6;
	public static final int MODE_CAPTURE_SAMPLE = 7;

	public Bitmap saveSignature(int mode) {
		return saveSignature(mode, Color.TRANSPARENT);
	}

	@SuppressWarnings("finally")
	public Bitmap saveSignature(int mode, int backgroundColor) {
		GameCanvasOption restoreOption = this.option.clone();
		this.option.mode = (mode == MODE_CAPTURE_FULL || mode == MODE_CAPTURE_SAMPLE) ? mode
				: MODE_CAPTURE_FULL;
		this.option.isHideArc = true;
		this.setAlign(ALIGN_CENTER);
		this.setShowAngle(false);
		this.setHideCorner(true);
		this.setHideHand(true);

		Bitmap bitmap = null;
		try {
			bitmap = Bitmap.createBitmap(doc_width, doc_height,
					Bitmap.Config.ARGB_8888);

			// bitmap.eraseColor(backgroundColor);
			Canvas c = new Canvas(bitmap);
			c.drawColor(backgroundColor);
			draw(c);

		} catch (OutOfMemoryError e) {
		} catch (Exception e) {
		} finally {
			this.option = restoreOption;
			this.option.isHideArc = this.option.isHideArc;
			this.setShowAngle(this.option.isShowAngle);
			this.setHideCorner(this.option.isHideCorner);
			this.setHideHand(this.option.isHideHand);
			this.setAlign(this.option.align);
			return bitmap;
		}
	}

	public void Initialize() {
		offset = new Point(0, 0);

		calSize();

		cosSeekBar.setProgress(Float.parseFloat(UDataStorage.getStrData(
				this.getContext(), "cosSeekValue", "0f")));

		tanSeekBar.setEnable(false);
		tanSeekBar.setHideCursor(true);
		mSinSeekBar.setCursorDirection(SeekBar.CURSOR_DIRECTION_R2L);
		setCosActive(true);
		calProgress(cosSeekBar, cosSeekBar.getProgress(), true);

		this.setActiveRegion(ACTIVE_REGION_SEEKBAR);
	}

	public void newStageWithAngle(boolean isCos, float angle) {
		angle = angle < 0.0f ? 0.0f : angle > 90.0f ? 90.0f : angle;

		if (isCos) {
			cosSeekBar.setProgress((float) (Math.cos((cosDegree = angle)
					* Math.PI / 180)));
			calProgress(cosSeekBar, cosSeekBar.getProgress(), true);
		} else {
			cosSeekBar.setProgress((float) (Math.cos((cosDegree = 90f - angle)
					* Math.PI / 180)));
			calProgress(cosSeekBar, cosSeekBar.getProgress(), true);
		}

	}

	public void newStageWithRedian(boolean isCos, float redian) {
		redian = redian < 0f ? 0f : redian > 1f ? 1f : redian;

		if (isCos) {
			cosSeekBar.setProgress(redian);
			calProgress(cosSeekBar, cosSeekBar.getProgress(), true);
		} else {
			sinSeekBar.setProgress(redian);
			calProgress(sinSeekBar, sinSeekBar.getProgress(), true);
		}
	}

	public float getSinAngle() {
		return 90f - cosDegree;
	}

	public float getCosAngle() {
		return cosDegree;
	}

	public float getSinRadian() {
		return this.sinSeekBar.getProgress();
	}

	public float getCosRadian() {
		return this.cosSeekBar.getProgress();
	}

	public void startFadeActive() {
		if (this.option.isCosActive) {
			this.mCosSeekBar.fadeActiveAnimation();
			this.cosSeekBar.fadeActiveAnimation();
		} else {
			this.mSinSeekBar.fadeActiveAnimation();
			this.sinSeekBar.fadeActiveAnimation();
		}
		this.fadeActiveAnimation();
	}

	private boolean isCosPosition = true;

	public void setLabelPosition(boolean isCosPosition) {
		this.isCosPosition = isCosPosition;
	}

	// ==========================================================
	// Listener Method
	// ==========================================================
	private InteractListener sinSeekBarListener;

	public void setSinListener(InteractListener listener) {
		this.sinSeekBarListener = listener;
		this.sinSeekBar.addListener(new SeekBarListener() {
			long lastTime = 0;

			@Override
			public void onSeekBarDragged(SeekBar obj, float progress) {
				sinSeekBarListener.onEndDrag(obj, progress,
						System.currentTimeMillis(), System.currentTimeMillis()
								- lastTime, obj.getCursorPoint());
			}

			@Override
			public void onSeekBarBeginDrag(SeekBar obj, float progress) {
				sinSeekBarListener.onBeginDrag(obj, progress,
						lastTime = System.currentTimeMillis(),
						obj.getCursorPoint());
			}

			@Override
			public void onSeekBarDragging(SeekBar obj, float progress) {
				sinSeekBarListener.onValueChange(obj, progress,
						System.currentTimeMillis(), obj.getCursorPoint());
			}
		});
	}

	private InteractListener cosSeekBarListener;

	public void setCosListener(InteractListener listener) {
		this.cosSeekBarListener = listener;
		this.cosSeekBar.addListener(new SeekBarListener() {
			long lastTime = 0;

			@Override
			public void onSeekBarDragged(SeekBar obj, float progress) {
				cosSeekBarListener.onEndDrag(obj, progress,
						System.currentTimeMillis(), System.currentTimeMillis()
								- lastTime, obj.getCursorPoint());
			}

			@Override
			public void onSeekBarBeginDrag(SeekBar obj, float progress) {
				cosSeekBarListener.onBeginDrag(obj, progress,
						lastTime = System.currentTimeMillis(),
						obj.getCursorPoint());
			}

			@Override
			public void onSeekBarDragging(SeekBar obj, float progress) {
				cosSeekBarListener.onValueChange(obj, progress,
						System.currentTimeMillis(), obj.getCursorPoint());
			}
		});
	}

	private InteractListener sinSlideListener;

	public void setSinSlideListener(InteractListener listener) {
		this.sinSlideListener = listener;
		this.mSinSeekBar.addListener(new SeekBarListener() {
			long lastTime = 0;

			@Override
			public void onSeekBarDragged(SeekBar obj, float progress) {
				sinSlideListener.onEndDrag(obj,
						(progress / option.thumb_length),
						System.currentTimeMillis(), System.currentTimeMillis()
								- lastTime, obj.getCursorPoint());
			}

			@Override
			public void onSeekBarBeginDrag(SeekBar obj, float progress) {
				sinSlideListener.onBeginDrag(obj,
						(progress / option.thumb_length),
						lastTime = System.currentTimeMillis(),
						obj.getCursorPoint());
			}

			@Override
			public void onSeekBarDragging(SeekBar obj, float progress) {
				sinSlideListener.onValueChange(obj,
						(progress / option.thumb_length),
						System.currentTimeMillis(), obj.getCursorPoint());
			}
		});
	}

	private InteractListener cosSlideListener;

	public void setCosSlideListener(InteractListener listener) {
		this.cosSlideListener = listener;
		this.mCosSeekBar.addListener(new SeekBarListener() {
			long lastTime = 0;

			@Override
			public void onSeekBarDragged(SeekBar obj, float progress) {
				cosSlideListener.onEndDrag(obj, progress / option.thumb_length,
						System.currentTimeMillis(), System.currentTimeMillis()
								- lastTime, obj.getCursorPoint());
			}

			@Override
			public void onSeekBarBeginDrag(SeekBar obj, float progress) {
				cosSlideListener.onBeginDrag(obj, progress
						/ option.thumb_length,
						lastTime = System.currentTimeMillis(),
						obj.getCursorPoint());
			}

			@Override
			public void onSeekBarDragging(SeekBar obj, float progress) {
				cosSlideListener.onValueChange(obj,
						(progress / option.thumb_length),
						System.currentTimeMillis(), obj.getCursorPoint());
			}
		});
	}

	private InteractClickListener sinSpinListener;

	public void setSinSpinListener(InteractClickListener listener) {
		this.sinSpinListener = listener;
	}

	private InteractClickListener cosSpinListener;

	public void setCosSpinListener(InteractClickListener listener) {
		this.cosSpinListener = listener;
	}

	private InteractClickListener sinPlusListener;

	public void setSinPlusListener(InteractClickListener listener) {
		this.sinPlusListener = listener;
	}

	private InteractClickListener cosPlusListener;

	public void setCosPlusListener(InteractClickListener listener) {
		this.cosPlusListener = listener;
	}

	private InteractClickListener sinMinusListener;

	public void setSinMinusListener(InteractClickListener listener) {
		this.sinMinusListener = listener;
	}

	private InteractClickListener cosMinusListener;

	public void setCosMinusListener(InteractClickListener listener) {
		this.cosMinusListener = listener;
	}

	// ==========================================================
	// Event Method
	// ==========================================================

	public void onResume() {
		if (corner_cos_anim != null)
			corner_cos_anim.start();
		if (corner_sin_anim != null)
			corner_sin_anim.start();
	}

	public void onDestroy() {
		if (corner_cos_anim != null)
			corner_cos_anim.stop();
		if (corner_sin_anim != null)
			corner_sin_anim.stop();
	}

	public void onFinish() {
		try {
			if (corner_cos_anim != null)
				corner_cos_anim.finish();
			if (corner_sin_anim != null)
				corner_sin_anim.finish();
			if (cosSeekBar != null)
				cosSeekBar.finish();
			if (sinSeekBar != null)
				sinSeekBar.finish();
			if (tanSeekBar != null)
				tanSeekBar.finish();
			if (mCosSeekBar != null)
				mCosSeekBar.finish();
			if (mSinSeekBar != null)
				mSinSeekBar.finish();
		} catch (Exception e) {
		}
	}

	@Override
	public void onClick(SpinButton obj) {
		if (obj == cosPlusBodaries) {
			float value = cosSeekBar.getProgress() + this.weight_point;
			cosSeekBar.setProgress(value > 1 ? 1 : value);
			calProgress(cosSeekBar, value, true);

			if (cosPlusListener != null)
				cosPlusListener.onClick(obj, cosSeekBar.getProgress(),
						System.currentTimeMillis(), new Point());

			Log.w("Trigle", "SpinClickListener=>Click Plus cosSeekBar" + value);
		}
		if (obj == sinPlusBodaries) {
			float value = sinSeekBar.getProgress() + this.weight_point;
			sinSeekBar.setProgress(value > 1 ? 1 : value);
			calProgress(sinSeekBar, value, true);
			Log.w("Trigle", "SpinClickListener=>Click Plus sinSeekBar" + value);
			if (sinPlusListener != null)
				sinPlusListener.onClick(obj, sinSeekBar.getProgress(),
						System.currentTimeMillis(), new Point());
		}

		if (obj == cosMinusBodaries) {
			float value = cosSeekBar.getProgress() - this.weight_point;
			cosSeekBar.setProgress(value < 0 ? 0 : value);
			calProgress(cosSeekBar, value, true);
			Log.w("Trigle", "SpinClickListener=>Click Minus cosSeekBar" + value);
			if (cosMinusListener != null)
				cosMinusListener.onClick(obj, cosSeekBar.getProgress(),
						System.currentTimeMillis(), new Point());
		}
		if (obj == sinMinusBodaries) {
			float value = sinSeekBar.getProgress() - this.weight_point;
			sinSeekBar.setProgress(value < 0 ? 0 : value);
			calProgress(sinSeekBar, value, true);
			Log.w("Trigle", "SpinClickListener=>Click Minus sinSeekBar" + value);
			if (sinMinusListener != null)
				sinMinusListener.onClick(obj, sinSeekBar.getProgress(),
						System.currentTimeMillis(), new Point());
		}

		if (obj == cosLabelBodaries)
			if (cosSpinListener != null)
				cosSpinListener.onClick(
						obj,
						cosSeekBar.getProgress(),
						System.currentTimeMillis(),
						new Point(cosLabelBodaries.bondary.left,
								cosLabelBodaries.bondary.top
										- (int) (cosLabelBodaries.bondary
												.height() / 2)));
		if (obj == sinLabelBodaries)
			if (sinSpinListener != null)
				sinSpinListener.onClick(
						obj,
						sinSeekBar.getProgress(),
						System.currentTimeMillis(),
						new Point(sinLabelBodaries.bondary.left,
								sinLabelBodaries.bondary.top
										- (int) (sinLabelBodaries.bondary
												.height() / 2)));

	}

	@Override
	protected void finalize() throws Throwable {
		try {
			if (corner_cos_anim != null)
				corner_cos_anim.finish();
			if (corner_sin_anim != null)
				corner_sin_anim.finish();
			if (cosSeekBar != null)
				cosSeekBar.finish();
			if (sinSeekBar != null)
				sinSeekBar.finish();
			if (tanSeekBar != null)
				tanSeekBar.finish();
			if (mCosSeekBar != null)
				mCosSeekBar.finish();
			if (mSinSeekBar != null)
				mSinSeekBar.finish();
		} catch (Exception e) {
		}
		super.finalize();
	}

	@Override
	public void onSeekBarDragged(SeekBar obj, float progress) {
		calProgress(obj, progress, true);
		if (!this.option.isViewForAnimate) {
			if (!this.option.isHideLabel && obj == mCosSeekBar)
				cosSeekBar.setCoverLabel(false);
			if (!this.option.isHideLabel && obj == mSinSeekBar)
				sinSeekBar.setCoverLabel(false);
		}
	}

	@Override
	public void onSeekBarDragging(SeekBar obj, float progress) {
		calProgress(obj, progress, false);
	}

	@Override
	public void onSeekBarBeginDrag(SeekBar obj, float progress) {
		if (!this.option.isViewForAnimate) {
			if (!this.option.isHideLabel && obj == mCosSeekBar)
				cosSeekBar.setCoverLabel(true);
			if (!this.option.isHideLabel && obj == mSinSeekBar)
				sinSeekBar.setCoverLabel(true);
		}
	}

	@SuppressLint("NewApi")
	@Override
	protected void onDraw(Canvas canvas) {

		boolean isDraw = !this.option.isViewForAnimate
				&& this.option.isShowSeekBar
				&& (this.option.mode == MODE_DISPLAY || this.option.mode == MODE_CAPTURE_FULL);

		drawAngle(canvas);
		drawArc(canvas);
		drawBar(canvas, isDraw);
		drawCursorAndUnit(canvas, isDraw);
		drawCorner(canvas);

		if (this.option.mode != MODE_DISPLAY)
			drawTopLabnel(canvas);
		else
			drawSpin2(canvas);
		drawLabel(canvas);
		drawHand(canvas);
	}

	// ======================================================================
	// DRAW HELPER
	// ======================================================================
	private void drawHand(Canvas canvas) {
		switch (this.option.pos_hand) {
		case POS_HAND_SLIDE:
			if (this.option.isMultiActive) {
				mSinSeekBar.drawHand(canvas);
				mCosSeekBar.drawHand(canvas);
			} else {
				if (!this.option.isCosActive)
					mSinSeekBar.drawHand(canvas);
				else
					mCosSeekBar.drawHand(canvas);
			}
			break;
		case POS_HAND_SEEKBAR:
			if (this.option.isMultiActive) {
				sinSeekBar.drawHand(canvas);
				cosSeekBar.drawHand(canvas);
			} else {
				if (!this.option.isCosActive)
					sinSeekBar.drawHand(canvas);
				else
					cosSeekBar.drawHand(canvas);
			}
			break;
		case POS_HAND_BOTH:
			if (this.option.isMultiActive) {
				sinSeekBar.drawHand(canvas);
				mSinSeekBar.drawHand(canvas);
				cosSeekBar.drawHand(canvas);
				mCosSeekBar.drawHand(canvas);
			} else {
				if (!this.option.isCosActive) {
					sinSeekBar.drawHand(canvas);
					mSinSeekBar.drawHand(canvas);
				} else {
					cosSeekBar.drawHand(canvas);
					mCosSeekBar.drawHand(canvas);
				}
			}
			break;
		}
	}

	private void drawAngle(Canvas canvas) {
		if (!this.option.isViewForAnimate && this.option.isShowAngle) {
			canvas.drawText(getContext().getString(R.string.display_cos),
					offset.x + this.object_width - 100 - 22, offset.y
							+ this.object_width - 20, anglePaint);
			canvas.drawText(String.format("% ." + this.option.num_float_bit
					+ "f", cosDegree), offset.x + 32 + this.object_width - 100,
					offset.y + this.object_width - 20, anglePaint);
			canvas.drawText(getContext().getString(R.string.display_sin),
					offset.x + 10, offset.y + 20, anglePaint);
			canvas.drawText(String.format("% ." + this.option.num_float_bit
					+ "f", (90f - cosDegree)), offset.x + 15 + 42,
					offset.y + 20, anglePaint);
		}

	}

	private void drawArc(Canvas canvas) {
		if (!this.option.isHideArc)
			if (!this.option.multiCorner) {
				if (this.option.isCosActive)
					canvas.drawArc(cosRectF, 180f, cosDegree, true,
							markAnglePaint);
				else
					canvas.drawArc(sinRectF, cosDegree, 90f - cosDegree, true,
							markAnglePaint);
			} else {

				canvas.drawArc(cosRectF, 180f, cosDegree, true, markAnglePaint);
				canvas.drawArc(sinRectF, cosDegree, 90f - cosDegree, true,
						markAnglePaint);
			}

	}

	private void drawBar(Canvas canvas, boolean isDraw) {
		if (isDraw) {
			cosSeekBar.drawLine(canvas);
			sinSeekBar.drawLine(canvas);
			tanSeekBar.drawLine(canvas);
		}

		mSinSeekBar.drawLine(canvas);
		mCosSeekBar.drawLine(canvas);

		canvas.drawLine(mCosSeekBar.getCursorX(), mCosSeekBar.getCursorY(),
				mSinSeekBar.getCursorX(), mSinSeekBar.getCursorY(), tanPaint);

	}

	private void drawCursorAndUnit(Canvas canvas, boolean isDraw) {

		if (isDraw) {
			cosSeekBar.drawCursor(canvas);
			sinSeekBar.drawCursor(canvas);
			tanSeekBar.drawCursor(canvas);

			cosSeekBar.drawUnit(canvas);
			sinSeekBar.drawUnit(canvas);
			tanSeekBar.drawUnit(canvas);
		}

		mSinSeekBar.drawCursor(canvas);
		mCosSeekBar.drawCursor(canvas);

	}

	private void drawLabel(Canvas canvas) {
		cosSeekBar.drawLabel(canvas);
		sinSeekBar.drawLabel(canvas);
		tanSeekBar.drawLabel(canvas);
	}

	private void drawCorner(Canvas canvas) {
		if (!this.option.isHideCorner) {
			if (this.option.multiCorner) {
				corner_cos_anim.Draw(canvas);
				corner_sin_anim.Draw(canvas);
			} else {
				if (this.option.isCosActive)
					corner_cos_anim.Draw(canvas);
				else
					corner_sin_anim.Draw(canvas);
			}
		}
	}

	private Drawable tmpIcon = null;

	private void drawSpin2(Canvas canvas) {
		try {
			if (/*
				 * this.option.mode == this.MODE_DISPLAY &&
				 */!this.option.isViewForAnimate) {
				tmpIcon = iconSpin30;
				int tmp_alpha = 255;
				if (this.option.isCosActive) {
					if (this.isPlaying()) {
						tmp_alpha = alpha;
						tmpRect = new Rect(iconCos.left, iconCos.top,
								iconCos.right, iconCos.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
					} else
						tmpRect = iconCos;
				} else
					tmpRect = iconCos;

				lineBarPaint.setAlpha(tmp_alpha);
				lineBarFillPaint.setAlpha(tmp_alpha);
				int radius = tmpRect.width();

				if (this.option.isCosActive) {

					drawableBG_Blue.setBounds(rectCosBg);
					drawableBG_Blue.draw(canvas);
					drawableBG_Red.setBounds(rectSinBg);
					drawableBG_Red.draw(canvas);
				}
				else
				{

					drawableBG_Red.setBounds(rectSinBg);
					drawableBG_Red.draw(canvas);
					drawableBG_Blue.setBounds(rectCosBg);
					drawableBG_Blue.draw(canvas);
				}
				if (this.option.isCosActive) {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, -cosDegree, true,
							lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((cosSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - sinSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);
				} else {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, cosDegree - 90,
							true, lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((sinSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - cosSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);

				}
				tmp_alpha = 255;
				if (!this.option.isCosActive) {
					if (this.isPlaying()) {
						tmp_alpha = alpha;
						tmpRect = new Rect(iconSin.left, iconSin.top,
								iconSin.right, iconSin.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
					} else
						tmpRect = iconSin;
				} else
					tmpRect = iconSin;

				lineBarPaint.setAlpha(tmp_alpha);
				lineBarFillPaint.setAlpha(tmp_alpha);
				radius = tmpRect.width();

				if (this.option.isCosActive) {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, -cosDegree, true,
							lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((cosSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - sinSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);
				} else {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, cosDegree - 90,
							true, lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((sinSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - cosSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);
				}
				if (active_region == ACTIVE_REGION_SPIN) {
					if (!cosMinusBodaries.pressed) {
						if (this.option.isCosActive && this.isPlaying()) {
							minusDrawable.setAlpha(alpha);
							tmpRect = new Rect(cosMinusBodaries.bondary.left,
									cosMinusBodaries.bondary.top,
									cosMinusBodaries.bondary.right,
									cosMinusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							minusDrawable.setBounds(tmpRect);
						} else {
							minusDrawable.setAlpha(255);
							minusDrawable.setBounds(cosMinusBodaries.bondary);
						}
						minusDrawable.draw(canvas);
					} else {
						if (this.option.isCosActive && this.isPlaying()) {
							minusHoverDrawable.setAlpha(alpha);
						} else {
							minusHoverDrawable.setAlpha(255);
						}
						tmpRect = new Rect(
								cosMinusBodaries.bondary.left
										- (int) (cosMinusBodaries.bondary
												.width() * 0.2),
								cosMinusBodaries.bondary.top
										- (int) (cosMinusBodaries.bondary
												.height() * 0.2),
								cosMinusBodaries.bondary.right
										+ (int) (cosMinusBodaries.bondary
												.width() * 0.2),
								cosMinusBodaries.bondary.bottom
										+ (int) (cosMinusBodaries.bondary
												.height() * 0.2));
						minusHoverDrawable.setBounds(tmpRect);
						minusHoverDrawable.draw(canvas);
					}
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						minusInactiveDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosMinusBodaries.bondary.left,
								cosMinusBodaries.bondary.top,
								cosMinusBodaries.bondary.right,
								cosMinusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						minusInactiveDrawable.setBounds(tmpRect);
					} else {
						minusInactiveDrawable.setAlpha(255);
						minusInactiveDrawable
								.setBounds(cosMinusBodaries.bondary);
					}
					minusInactiveDrawable.draw(canvas);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (this.option.isCosActive && this.isPlaying()) {
						labelDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosLabelBodaries.bondary.left,
								cosLabelBodaries.bondary.top,
								cosLabelBodaries.bondary.right,
								cosLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						labelDrawable.setBounds(tmpRect);
					} else {
						labelDrawable.setAlpha(255);
						labelDrawable.setBounds(cosLabelBodaries.bondary);
					}
					labelDrawable.draw(canvas);
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						inactiveLabelDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosLabelBodaries.bondary.left,
								cosLabelBodaries.bondary.top,
								cosLabelBodaries.bondary.right,
								cosLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						inactiveLabelDrawable.setBounds(tmpRect);
					} else {
						inactiveLabelDrawable.setAlpha(255);
						inactiveLabelDrawable
								.setBounds(cosLabelBodaries.bondary);
					}
					inactiveLabelDrawable.draw(canvas);
				}

				String label = String.format("%.3f", cosSeekBar.getProgress());
				if (active_region == ACTIVE_REGION_SPIN) {
					if (this.option.isCosActive && this.isPlaying()) {
						titlePaint.setAlpha((int) (0.5f * alpha));
						spinPaint.setAlpha((int) (0.5f * alpha));
					} else {
						titlePaint.setAlpha(255);
						spinPaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									!isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtCosSpinTxt.x, vtCosSpinTxt.y, titlePaint);
					canvas.drawText(
							label,
							cosLabelBodaries.bondary.left
									+ (cosLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							cosLabelBodaries.bondary.top
									+ (cosLabelBodaries.bondary.height() + (spinPaint
											.descent() - spinPaint.ascent()) / 4)
									/ 2, spinPaint);
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						titleInactivePaint.setAlpha((int) (0.5f * alpha));
						spinInactivePaint.setAlpha((int) (0.5f * alpha));
					} else {
						titleInactivePaint.setAlpha(255);
						spinInactivePaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									!isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtCosSpinTxt.x, vtCosSpinTxt.y, titleInactivePaint);
					canvas.drawText(
							label,
							cosLabelBodaries.bondary.left
									+ (cosLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							cosLabelBodaries.bondary.top
									+ (cosLabelBodaries.bondary.height() + (spinInactivePaint
											.descent() - spinInactivePaint
											.ascent()) / 4) / 2,
							spinInactivePaint);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!cosPlusBodaries.pressed) {
						if (this.option.isCosActive && this.isPlaying()) {
							plusDrawable.setAlpha(alpha);
							tmpRect = new Rect(cosPlusBodaries.bondary.left,
									cosPlusBodaries.bondary.top,
									cosPlusBodaries.bondary.right,
									cosPlusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							plusDrawable.setBounds(tmpRect);
						} else {
							plusDrawable.setAlpha(255);
							plusDrawable.setBounds(cosPlusBodaries.bondary);
						}
						plusDrawable.draw(canvas);
					} else {
						if (this.option.isCosActive && this.isPlaying()) {
							plusHoverDrawable.setAlpha(alpha);
						} else {
							plusHoverDrawable.setAlpha(255);
						}
						tmpRect = new Rect(
								cosPlusBodaries.bondary.left
										- (int) (cosPlusBodaries.bondary
												.width() * 0.2),
								cosPlusBodaries.bondary.top
										- (int) (cosPlusBodaries.bondary
												.height() * 0.2),
								cosPlusBodaries.bondary.right
										+ (int) (cosPlusBodaries.bondary
												.width() * 0.2),
								cosPlusBodaries.bondary.bottom
										+ (int) (cosPlusBodaries.bondary
												.height() * 0.2));
						plusHoverDrawable.setBounds(tmpRect);
						plusHoverDrawable.draw(canvas);
					}
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						plusInactiveDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosPlusBodaries.bondary.left,
								cosPlusBodaries.bondary.top,
								cosPlusBodaries.bondary.right,
								cosPlusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						plusInactiveDrawable.setBounds(tmpRect);
					} else {
						plusInactiveDrawable.setAlpha(255);
						plusInactiveDrawable.setBounds(cosPlusBodaries.bondary);
						;
					}
					plusInactiveDrawable.draw(canvas);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!sinMinusBodaries.pressed) {
						if (!this.option.isCosActive && this.isPlaying()) {
							tmpRect = new Rect(sinMinusBodaries.bondary.left,
									sinMinusBodaries.bondary.top,
									sinMinusBodaries.bondary.right,
									sinMinusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							minusDrawable.setBounds(tmpRect);
							minusDrawable.setAlpha(alpha);
						} else {
							minusDrawable.setBounds(sinMinusBodaries.bondary);
							minusDrawable.setAlpha(255);
						}
						minusDrawable.draw(canvas);
					} else {
						if (!this.option.isCosActive && this.isPlaying()) {
							minusHoverDrawable.setAlpha(alpha);
						} else {
							minusHoverDrawable.setAlpha(255);
						}
						tmpRect = new Rect(
								sinMinusBodaries.bondary.left
										- (int) (sinMinusBodaries.bondary
												.width() * 0.2),
								sinMinusBodaries.bondary.top
										- (int) (sinMinusBodaries.bondary
												.height() * 0.2),
								sinMinusBodaries.bondary.right
										+ (int) (sinMinusBodaries.bondary
												.width() * 0.2),
								sinMinusBodaries.bondary.bottom
										+ (int) (sinMinusBodaries.bondary
												.height() * 0.2));
						minusHoverDrawable.setBounds(tmpRect);
						minusHoverDrawable.draw(canvas);
					}
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {

						tmpRect = new Rect(sinMinusBodaries.bondary.left,
								sinMinusBodaries.bondary.top,
								sinMinusBodaries.bondary.right,
								sinMinusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						minusInactiveDrawable.setBounds(tmpRect);
						minusInactiveDrawable.setAlpha(alpha);
					} else {
						minusInactiveDrawable
								.setBounds(sinMinusBodaries.bondary);
						minusInactiveDrawable.setAlpha(255);
					}
					minusInactiveDrawable.draw(canvas);
				}

				if (active_region == ACTIVE_REGION_SPIN) {

					if (!this.option.isCosActive && this.isPlaying()) {
						tmpRect = new Rect(sinLabelBodaries.bondary.left,
								sinLabelBodaries.bondary.top,
								sinLabelBodaries.bondary.right,
								sinLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						labelDrawable.setAlpha(alpha);
						labelDrawable.setBounds(tmpRect);
					} else {
						labelDrawable.setAlpha(255);
						labelDrawable.setBounds(sinLabelBodaries.bondary);
					}
					labelDrawable.draw(canvas);
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {
						tmpRect = new Rect(sinLabelBodaries.bondary.left,
								sinLabelBodaries.bondary.top,
								sinLabelBodaries.bondary.right,
								sinLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						inactiveLabelDrawable.setBounds(tmpRect);
						inactiveLabelDrawable.setAlpha(alpha);
					} else {
						inactiveLabelDrawable.setAlpha(255);
						inactiveLabelDrawable
								.setBounds(sinLabelBodaries.bondary);
					}
					inactiveLabelDrawable.draw(canvas);
				}

				label = String.format("%.3f", sinSeekBar.getProgress());
				if (active_region == ACTIVE_REGION_SPIN) {
					if (!this.option.isCosActive && this.isPlaying()) {
						titlePaint.setAlpha((int) (0.5f * alpha));
						spinPaint.setAlpha((int) (0.5f * alpha));
					} else {
						titlePaint.setAlpha(255);
						spinPaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtSinSpinTxt.x, vtSinSpinTxt.y, titlePaint);
					canvas.drawText(
							label,
							sinLabelBodaries.bondary.left
									+ (sinLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							sinLabelBodaries.bondary.top
									+ (sinLabelBodaries.bondary.height() + (spinInactivePaint
											.descent() - spinInactivePaint
											.ascent()) / 4) / 2, spinPaint);
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {
						titleInactivePaint.setAlpha((int) (0.5f * alpha));
						spinInactivePaint.setAlpha((int) (0.5f * alpha));
					} else {
						titleInactivePaint.setAlpha(255);
						spinInactivePaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtSinSpinTxt.x, vtSinSpinTxt.y, titleInactivePaint);
					canvas.drawText(
							label,
							sinLabelBodaries.bondary.left
									+ (sinLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							sinLabelBodaries.bondary.top
									+ (sinLabelBodaries.bondary.height() + (spinInactivePaint
											.descent() - spinInactivePaint
											.ascent()) / 4) / 2,
							spinInactivePaint);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!sinPlusBodaries.pressed) {
						if (!this.option.isCosActive && this.isPlaying()) {
							tmpRect = new Rect(sinPlusBodaries.bondary.left,
									sinPlusBodaries.bondary.top,
									sinPlusBodaries.bondary.right,
									sinPlusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							plusDrawable.setBounds(tmpRect);
							plusDrawable.setAlpha(alpha);
						} else {
							plusDrawable.setAlpha(255);
							plusDrawable.setBounds(sinPlusBodaries.bondary);
						}
						plusDrawable.draw(canvas);
					} else {
						tmpRect = new Rect(
								sinPlusBodaries.bondary.left
										- (int) (sinPlusBodaries.bondary
												.width() * 0.2),
								sinPlusBodaries.bondary.top
										- (int) (sinPlusBodaries.bondary
												.height() * 0.2),
								sinPlusBodaries.bondary.right
										+ (int) (sinPlusBodaries.bondary
												.width() * 0.2),
								sinPlusBodaries.bondary.bottom
										+ (int) (sinPlusBodaries.bondary
												.height() * 0.2));
						if (!this.option.isCosActive && this.isPlaying()) {
							plusHoverDrawable.setAlpha(alpha);
						} else {
							plusHoverDrawable.setAlpha(255);
						}
						plusHoverDrawable.setBounds(tmpRect);
						plusHoverDrawable.draw(canvas);
					}
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {
						plusInactiveDrawable.setAlpha(alpha);
						tmpRect = new Rect(sinPlusBodaries.bondary.left,
								sinPlusBodaries.bondary.top,
								sinPlusBodaries.bondary.right,
								sinPlusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						plusInactiveDrawable.setBounds(tmpRect);
					} else {
						plusInactiveDrawable.setAlpha(255);
						plusInactiveDrawable.setBounds(sinPlusBodaries.bondary);
					}
					plusInactiveDrawable.draw(canvas);
				}
			}
		} catch (Exception e) {
		}
	}

	private void drawSpin(Canvas canvas) {
		try {
			if (/*
				 * this.option.mode == this.MODE_DISPLAY &&
				 */!this.option.isViewForAnimate) {

				tmpIcon = iconSpin30;
				int tmp_alpha = 255;
				if (this.option.isCosActive) {
					if (this.isPlaying()) {
						tmp_alpha = alpha;
						tmpRect = new Rect(iconCos.left, iconCos.top,
								iconCos.right, iconCos.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
					} else
						tmpRect = iconCos;
				} else
					tmpRect = iconCos;

				lineBarPaint.setAlpha(tmp_alpha);
				lineBarFillPaint.setAlpha(tmp_alpha);
				int radius = tmpRect.width();

				if (this.option.isCosActive) {

					drawableBG_Blue.setBounds(rectCosBg);
					drawableBG_Blue.draw(canvas);
					drawableBG_Red.setBounds(rectSinBg);
					drawableBG_Red.draw(canvas);
				}
				else
				{

					drawableBG_Red.setBounds(rectSinBg);
					drawableBG_Red.draw(canvas);
					drawableBG_Blue.setBounds(rectCosBg);
					drawableBG_Blue.draw(canvas);
				}
				if (this.option.isCosActive) {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, -cosDegree, true,
							lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((cosSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - sinSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);

				} else {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, cosDegree - 90,
							true, lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((sinSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - cosSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);

				}
				tmp_alpha = 255;
				if (!this.option.isCosActive) {
					if (this.isPlaying()) {
						tmp_alpha = alpha;
						tmpRect = new Rect(iconSin.left, iconSin.top,
								iconSin.right, iconSin.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
					} else
						tmpRect = iconSin;
				} else
					tmpRect = iconSin;

				lineBarPaint.setAlpha(tmp_alpha);
				lineBarFillPaint.setAlpha(tmp_alpha);
				radius = tmpRect.width();

				if (this.option.isCosActive) {
					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, cosDegree - 90,
							true, lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((sinSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - cosSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);

				} else {

					canvas.drawArc(new RectF(tmpRect.left - tmpRect.width(),
							tmpRect.top, tmpRect.right, tmpRect.bottom
									+ tmpRect.height()), 0f, -cosDegree, true,
							lineBarFillPaint);
					canvas.drawLine(tmpRect.left, tmpRect.bottom,
							tmpRect.right, tmpRect.bottom, lineBarPaint);
					canvas.drawLine(
							tmpRect.left
									+ (int) ((cosSeekBar.getProgress()) * radius),
							tmpRect.top
									+ (int) ((1f - sinSeekBar.getProgress()) * radius),
							tmpRect.left, tmpRect.bottom, lineBarPaint);

				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!cosMinusBodaries.pressed) {
						if (this.option.isCosActive && this.isPlaying()) {
							minusDrawable.setAlpha(alpha);
							tmpRect = new Rect(cosMinusBodaries.bondary.left,
									cosMinusBodaries.bondary.top,
									cosMinusBodaries.bondary.right,
									cosMinusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							minusDrawable.setBounds(tmpRect);
						} else {
							minusDrawable.setAlpha(255);
							minusDrawable.setBounds(cosMinusBodaries.bondary);
						}
						minusDrawable.draw(canvas);
					} else {
						if (this.option.isCosActive && this.isPlaying()) {
							minusHoverDrawable.setAlpha(alpha);
						} else {
							minusHoverDrawable.setAlpha(255);
						}
						tmpRect = new Rect(
								cosMinusBodaries.bondary.left
										- (int) (cosMinusBodaries.bondary
												.width() * 0.2),
								cosMinusBodaries.bondary.top
										- (int) (cosMinusBodaries.bondary
												.height() * 0.2),
								cosMinusBodaries.bondary.right
										+ (int) (cosMinusBodaries.bondary
												.width() * 0.2),
								cosMinusBodaries.bondary.bottom
										+ (int) (cosMinusBodaries.bondary
												.height() * 0.2));
						minusHoverDrawable.setBounds(tmpRect);
						minusHoverDrawable.draw(canvas);
					}
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						minusInactiveDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosMinusBodaries.bondary.left,
								cosMinusBodaries.bondary.top,
								cosMinusBodaries.bondary.right,
								cosMinusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						minusInactiveDrawable.setBounds(tmpRect);
					} else {
						minusInactiveDrawable.setAlpha(255);
						minusInactiveDrawable
								.setBounds(cosMinusBodaries.bondary);
					}
					minusInactiveDrawable.draw(canvas);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (this.option.isCosActive && this.isPlaying()) {
						labelDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosLabelBodaries.bondary.left,
								cosLabelBodaries.bondary.top,
								cosLabelBodaries.bondary.right,
								cosLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						labelDrawable.setBounds(tmpRect);
					} else {
						labelDrawable.setAlpha(255);
						labelDrawable.setBounds(cosLabelBodaries.bondary);
					}
					labelDrawable.draw(canvas);
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						inactiveLabelDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosLabelBodaries.bondary.left,
								cosLabelBodaries.bondary.top,
								cosLabelBodaries.bondary.right,
								cosLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						inactiveLabelDrawable.setBounds(tmpRect);
					} else {
						inactiveLabelDrawable.setAlpha(255);
						inactiveLabelDrawable
								.setBounds(cosLabelBodaries.bondary);
					}
					inactiveLabelDrawable.draw(canvas);
				}

				String label = String.format("%.3f", cosSeekBar.getProgress());
				if (active_region == ACTIVE_REGION_SPIN) {
					if (this.option.isCosActive && this.isPlaying()) {
						titlePaint.setAlpha((int) (0.5f * alpha));
						spinPaint.setAlpha((int) (0.5f * alpha));
					} else {
						titlePaint.setAlpha(255);
						spinPaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									!isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtCosSpinTxt.x, vtCosSpinTxt.y, titlePaint);
					canvas.drawText(
							label,
							cosLabelBodaries.bondary.left
									+ (cosLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							cosLabelBodaries.bondary.top
									+ (cosLabelBodaries.bondary.height() + (spinPaint
											.descent() - spinPaint.ascent()) / 4)
									/ 2, spinPaint);
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						titleInactivePaint.setAlpha((int) (0.5f * alpha));
						spinInactivePaint.setAlpha((int) (0.5f * alpha));
					} else {
						titleInactivePaint.setAlpha(255);
						spinInactivePaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									!isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtCosSpinTxt.x, vtCosSpinTxt.y, titleInactivePaint);
					canvas.drawText(
							label,
							cosLabelBodaries.bondary.left
									+ (cosLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							cosLabelBodaries.bondary.top
									+ (cosLabelBodaries.bondary.height() + (spinInactivePaint
											.descent() - spinInactivePaint
											.ascent()) / 4) / 2,
							spinInactivePaint);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!cosPlusBodaries.pressed) {
						if (this.option.isCosActive && this.isPlaying()) {
							plusDrawable.setAlpha(alpha);
							tmpRect = new Rect(cosPlusBodaries.bondary.left,
									cosPlusBodaries.bondary.top,
									cosPlusBodaries.bondary.right,
									cosPlusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							plusDrawable.setBounds(tmpRect);
						} else {
							plusDrawable.setAlpha(255);
							plusDrawable.setBounds(cosPlusBodaries.bondary);
						}
						plusDrawable.draw(canvas);
					} else {
						if (this.option.isCosActive && this.isPlaying()) {
							plusHoverDrawable.setAlpha(alpha);
						} else {
							plusHoverDrawable.setAlpha(255);
						}
						tmpRect = new Rect(
								cosPlusBodaries.bondary.left
										- (int) (cosPlusBodaries.bondary
												.width() * 0.2),
								cosPlusBodaries.bondary.top
										- (int) (cosPlusBodaries.bondary
												.height() * 0.2),
								cosPlusBodaries.bondary.right
										+ (int) (cosPlusBodaries.bondary
												.width() * 0.2),
								cosPlusBodaries.bondary.bottom
										+ (int) (cosPlusBodaries.bondary
												.height() * 0.2));
						plusHoverDrawable.setBounds(tmpRect);
						plusHoverDrawable.draw(canvas);
					}
				} else {
					if (this.option.isCosActive && this.isPlaying()) {
						plusInactiveDrawable.setAlpha(alpha);
						tmpRect = new Rect(cosPlusBodaries.bondary.left,
								cosPlusBodaries.bondary.top,
								cosPlusBodaries.bondary.right,
								cosPlusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						plusInactiveDrawable.setBounds(tmpRect);
					} else {
						plusInactiveDrawable.setAlpha(255);
						plusInactiveDrawable.setBounds(cosPlusBodaries.bondary);
						;
					}
					plusInactiveDrawable.draw(canvas);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!sinMinusBodaries.pressed) {
						if (!this.option.isCosActive && this.isPlaying()) {
							tmpRect = new Rect(sinMinusBodaries.bondary.left,
									sinMinusBodaries.bondary.top,
									sinMinusBodaries.bondary.right,
									sinMinusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							minusDrawable.setBounds(tmpRect);
							minusDrawable.setAlpha(alpha);
						} else {
							minusDrawable.setBounds(sinMinusBodaries.bondary);
							minusDrawable.setAlpha(255);
						}
						minusDrawable.draw(canvas);
					} else {
						if (!this.option.isCosActive && this.isPlaying()) {
							minusHoverDrawable.setAlpha(alpha);
						} else {
							minusHoverDrawable.setAlpha(255);
						}
						tmpRect = new Rect(
								sinMinusBodaries.bondary.left
										- (int) (sinMinusBodaries.bondary
												.width() * 0.2),
								sinMinusBodaries.bondary.top
										- (int) (sinMinusBodaries.bondary
												.height() * 0.2),
								sinMinusBodaries.bondary.right
										+ (int) (sinMinusBodaries.bondary
												.width() * 0.2),
								sinMinusBodaries.bondary.bottom
										+ (int) (sinMinusBodaries.bondary
												.height() * 0.2));
						minusHoverDrawable.setBounds(tmpRect);
						minusHoverDrawable.draw(canvas);
					}
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {

						tmpRect = new Rect(sinMinusBodaries.bondary.left,
								sinMinusBodaries.bondary.top,
								sinMinusBodaries.bondary.right,
								sinMinusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						minusInactiveDrawable.setBounds(tmpRect);
						minusInactiveDrawable.setAlpha(alpha);
					} else {
						minusInactiveDrawable
								.setBounds(sinMinusBodaries.bondary);
						minusInactiveDrawable.setAlpha(255);
					}
					minusInactiveDrawable.draw(canvas);
				}

				if (active_region == ACTIVE_REGION_SPIN) {

					if (!this.option.isCosActive && this.isPlaying()) {
						tmpRect = new Rect(sinLabelBodaries.bondary.left,
								sinLabelBodaries.bondary.top,
								sinLabelBodaries.bondary.right,
								sinLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						labelDrawable.setAlpha(alpha);
						labelDrawable.setBounds(tmpRect);
					} else {
						labelDrawable.setAlpha(255);
						labelDrawable.setBounds(sinLabelBodaries.bondary);
					}
					labelDrawable.draw(canvas);
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {
						tmpRect = new Rect(sinLabelBodaries.bondary.left,
								sinLabelBodaries.bondary.top,
								sinLabelBodaries.bondary.right,
								sinLabelBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						inactiveLabelDrawable.setBounds(tmpRect);
						inactiveLabelDrawable.setAlpha(alpha);
					} else {
						inactiveLabelDrawable.setAlpha(255);
						inactiveLabelDrawable
								.setBounds(sinLabelBodaries.bondary);
					}
					inactiveLabelDrawable.draw(canvas);
				}

				label = String.format("%.3f", sinSeekBar.getProgress());
				if (active_region == ACTIVE_REGION_SPIN) {
					if (!this.option.isCosActive && this.isPlaying()) {
						titlePaint.setAlpha((int) (0.5f * alpha));
						spinPaint.setAlpha((int) (0.5f * alpha));
					} else {
						titlePaint.setAlpha(255);
						spinPaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtSinSpinTxt.x, vtSinSpinTxt.y, titlePaint);
					canvas.drawText(
							label,
							sinLabelBodaries.bondary.left
									+ (sinLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							sinLabelBodaries.bondary.top
									+ (sinLabelBodaries.bondary.height() + (spinInactivePaint
											.descent() - spinInactivePaint
											.ascent()) / 4) / 2, spinPaint);
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {
						titleInactivePaint.setAlpha((int) (0.5f * alpha));
						spinInactivePaint.setAlpha((int) (0.5f * alpha));
					} else {
						titleInactivePaint.setAlpha(255);
						spinInactivePaint.setAlpha(255);
					}
					canvas.drawText(
							this.getResources().getString(
									isCosPosition ? R.string.display_cos
											: R.string.display_sin),
							vtSinSpinTxt.x, vtSinSpinTxt.y, titleInactivePaint);
					canvas.drawText(
							label,
							sinLabelBodaries.bondary.left
									+ (sinLabelBodaries.bondary.width() - spinPaint
											.measureText(label)) / 2,
							sinLabelBodaries.bondary.top
									+ (sinLabelBodaries.bondary.height() + (spinInactivePaint
											.descent() - spinInactivePaint
											.ascent()) / 4) / 2,
							spinInactivePaint);
				}

				if (active_region == ACTIVE_REGION_SPIN) {
					if (!sinPlusBodaries.pressed) {
						if (!this.option.isCosActive && this.isPlaying()) {
							tmpRect = new Rect(sinPlusBodaries.bondary.left,
									sinPlusBodaries.bondary.top,
									sinPlusBodaries.bondary.right,
									sinPlusBodaries.bondary.bottom);

							tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
							tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
							plusDrawable.setBounds(tmpRect);
							plusDrawable.setAlpha(alpha);
						} else {
							plusDrawable.setAlpha(255);
							plusDrawable.setBounds(sinPlusBodaries.bondary);
						}
						plusDrawable.draw(canvas);
					} else {
						tmpRect = new Rect(
								sinPlusBodaries.bondary.left
										- (int) (sinPlusBodaries.bondary
												.width() * 0.2),
								sinPlusBodaries.bondary.top
										- (int) (sinPlusBodaries.bondary
												.height() * 0.2),
								sinPlusBodaries.bondary.right
										+ (int) (sinPlusBodaries.bondary
												.width() * 0.2),
								sinPlusBodaries.bondary.bottom
										+ (int) (sinPlusBodaries.bondary
												.height() * 0.2));
						if (!this.option.isCosActive && this.isPlaying()) {
							plusHoverDrawable.setAlpha(alpha);
						} else {
							plusHoverDrawable.setAlpha(255);
						}
						plusHoverDrawable.setBounds(tmpRect);
						plusHoverDrawable.draw(canvas);
					}
				} else {
					if (!this.option.isCosActive && this.isPlaying()) {
						plusInactiveDrawable.setAlpha(alpha);
						tmpRect = new Rect(sinPlusBodaries.bondary.left,
								sinPlusBodaries.bondary.top,
								sinPlusBodaries.bondary.right,
								sinPlusBodaries.bondary.bottom);

						tmpRect.top -= (zoom_anim * tmpRect.height() / 2);
						tmpRect.bottom += (zoom_anim * tmpRect.height() / 2);
						plusInactiveDrawable.setBounds(tmpRect);
					} else {
						plusInactiveDrawable.setAlpha(255);
						plusInactiveDrawable.setBounds(sinPlusBodaries.bondary);
					}
					plusInactiveDrawable.draw(canvas);
				}
			}
		} catch (Exception e) {
		}
	}

	@SuppressLint("DefaultLocale")
	private void drawTopLabnel(Canvas canvas) {
		try {
			float degree = (int) cosDegree;
			String label = String.format(
					(option.isCosActive ? "Cos " + String.format("%.1f", degree ): "Sin "
							+ String.format("%.1f", 90 - degree))
							+ getContext().getString(R.string.degree_symbol)
							+ " = %.3f", cosSeekBar.getProgress());
			if (this.option.isCosActive && this.isPlaying()) {
				spinCPaint.setAlpha((int) (0.5f * alpha));
			} else {
				spinCPaint.setAlpha(255);
			}
			canvas.drawText(
					label,
					cosLabelBodaries.bondary.left
							- (int) ((((float) object_width) / 320f) * 30)
							+ (cosLabelBodaries.bondary.width() - spinPaint
									.measureText(label)) / 2,
					cosLabelBodaries.bondary.top
							+ (cosLabelBodaries.bondary.height() + (spinPaint
									.descent() - spinPaint.ascent()) / 4) / 2,
					spinCPaint);

			label = String.format(
					(!option.isCosActive ? "Cos " + String.format("%.1f", degree) : "Sin "
							+ String.format("%.1f", 90 - degree))
							+ getContext().getString(R.string.degree_symbol)
							+ " = %.3f", sinSeekBar.getProgress());
			if (!this.option.isCosActive && this.isPlaying()) {
				spinCPaint.setAlpha((int) (0.5f * alpha));
			} else {
				spinCPaint.setAlpha(255);
			}
			canvas.drawText(
					label,
					sinLabelBodaries.bondary.left
							- (int) ((((float) object_width) / 320f) * 30)
							+ (sinLabelBodaries.bondary.width() - spinPaint
									.measureText(label)) / 2,
					sinLabelBodaries.bondary.top
							+ (sinLabelBodaries.bondary.height() + (spinInactivePaint
									.descent() - spinInactivePaint.ascent()) / 4)
							/ 2, spinCPaint);
			if (this.option.isCosActive) {
				String label2 = String.format("%.1f", cosDegree)
						+ getContext().getString(R.string.degree_symbol);
				canvas.drawText(
						label2,
						cosRectF.left - anglePaint.measureText(label2) < cosSeekBar
								.getPosition().x ? cosRectF.centerX() + 5 * aw
								: 20 > cosDegree ? cosRectF.centerX()
										- anglePaint.measureText(label2)
										: cosRectF.left
												- anglePaint
														.measureText(label2),
						cosDegree < 20 ? cosRectF.bottom - cosRectF.height()
								/ 2 - 15 * aw : cosRectF.bottom
								- cosRectF.height() / 2 - 15 * aw, anglePaint);
			} else {
				String label2 = String.format("%.1f", (90f - cosDegree))
						+ getContext().getString(R.string.degree_symbol);
				canvas.drawText(label2,
						sinRectF.left + (int) ((0.6) * sinRectF.width()),
						90f - cosDegree > 80 ? sinRectF.top - sinRectF.height()
								/ 2 : 90f - cosDegree < 30 ? sinRectF.top
								+ sinRectF.height() / 2 : sinRectF.bottom,
						anglePaint);
			}
		} catch (Exception e) {
		}
	}

	// **********************************************************************
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		super.onTouchEvent(event);

		if (this.option.mode == MODE_DISPLAY) {
			// grab the pointer id
			int action = event.getAction();
			int pid = action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
			int x = (int) event.getX(pid);
			int y = (int) event.getY(pid);
			if (!this.option.isLock) {
				return (touchSeekBar(action, x, y) || touchSpin(action, x, y));
			}

		}
		return false;
	}

	// ==========================================================
	// Animation Field
	// ==========================================================
	private CustomAnimation anim = new CustomAnimation();
	private Rect tmpRect = null;
	private float zoom_in_anim = 1.6f;
	private float zoom_anim = 0f;
	private boolean playing = false;
	private int alpha = 255;
	private int delay = 100;

	// ==========================================================
	// Animation Public Method
	// ==========================================================
	public boolean isPlaying() {
		return playing;
	}

	public void fadeActiveAnimation() {
		zoom_anim = zoom_in_anim;
		playing = true;
		anim.setInterval(delay);
		alpha = 0;
		anim.setListener(new TimerListener() {

			@Override
			public void onTimeUpdate(CustomAnimation obj, long totalTime,
					long deltaTime) {
				zoom_anim -= (float) Math.abs(Math.sin(zoom_anim)) * 0.42;
				alpha = (int) (Math.sin(zoom_in_anim - zoom_anim) * 255);
				if (zoom_anim <= 0.15f) {
					anim.EndAnimation();
					zoom_anim = 0f;
					alpha = 255;
					postInvalidate();
					playing = false;
					obj.StopAnimation();
				} else
					postInvalidate();
			}
		});
		anim.StartAnimation();
		postInvalidate();
	}

	// ======================================================================
	// SPIN HELPER
	// ======================================================================
	public class SpinButton {
		public Rect bondary = null;
		public boolean pressed = false;
		public SpinClickListener listener = null;

		public SpinButton() {
		}

		public boolean onTouch(int action, int x, int y) {
			if (action == MotionEvent.ACTION_DOWN) {
				if (bondary.contains(x, y)) {
					if (!pressed) {
						pressed = true;
						if (listener != null)
							listener.onClick(this);
					}
					invalidate();
					return true;
				}
			} else if (action == MotionEvent.ACTION_UP
					|| action == MotionEvent.ACTION_CANCEL) {
				if (pressed) {
					pressed = false;
					invalidate();
					return false;
				}
			}
			return false;
		}
	}

	public static int ACTIVE_REGION_SEEKBAR = 1;
	public static int ACTIVE_REGION_SPIN = 2;
	private int active_region = ACTIVE_REGION_SEEKBAR;

	public void setActiveRegion(int active_region) {
		this.active_region = (active_region == ACTIVE_REGION_SEEKBAR || active_region == ACTIVE_REGION_SPIN) ? active_region
				: ACTIVE_REGION_SEEKBAR;
		this.invalidate();
	}

	private boolean touchSeekBar(int action, int x, int y) {
		if (active_region == ACTIVE_REGION_SEEKBAR) {
			return cosSeekBar.onTouch(action, x, y)
					|| sinSeekBar.onTouch(action, x, y)
					// || tanSeekBar.onTouch(action, x, y)
					|| mSinSeekBar.onTouch(action, x, y)
					|| mCosSeekBar.onTouch(action, x, y);
		}
		return false;
	}

	private boolean touchSpin(int action, int x, int y) {
		if (active_region == ACTIVE_REGION_SPIN) {
			if (this.option.mode == this.MODE_DISPLAY
					&& !this.option.isViewForAnimate) {

				if ((cosMinusBodaries.onTouch(action, x, y)
						|| cosLabelBodaries.onTouch(action, x, y)
						|| cosPlusBodaries.onTouch(action, x, y)
						|| sinMinusBodaries.onTouch(action, x, y)
						|| sinLabelBodaries.onTouch(action, x, y) || sinPlusBodaries
							.onTouch(action, x, y))) {
					return true;
				} else if (!this.option.isHideCorner)
					return ((corner_sin_anim != null && corner_sin_anim
							.onTouch(action, x, y)) || (corner_cos_anim != null && corner_cos_anim
							.onTouch(action, x, y)));

			}
		}
		return false;
	}

	// **********************************************************************

	@Override
	protected void onSizeChanged(int width, int height, int oldw, int oldh) {
		super.onSizeChanged(width, height, oldw, oldh);

		if (this.option.mode == MODE_DISPLAY && width != doc_width
				|| height != doc_height) {
			doc_width = width;
			doc_height = height;
			calSize();
		}
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		if (this.option.mode == MODE_DISPLAY
				&& this.getMeasuredWidth() != doc_width
				|| this.getMeasuredHeight() != doc_height) {
			doc_width = this.getMeasuredWidth();
			doc_height = this.getMeasuredHeight();
			calSize();
		}
	}

	@Override
	public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		if (this.option.mode == MODE_DISPLAY
				&& this.getMeasuredWidth() != doc_width
				|| this.getMeasuredHeight() != doc_height) {
			doc_width = this.getMeasuredWidth();
			doc_height = this.getMeasuredHeight();
			calSize();
		}

	}

}